<template>
  <div
    ref="threeJsContainer"
    class="three-js-container"
    @click="onDocumentMouseDown"
  >
    <div ref="progressBar" class="progress-bar">Loading: 0%</div>
  </div>
</template>

<script setup>
import * as THREE from "three";
import { onMounted, ref } from "vue";
// 导入FBXLoader
import { FBXLoader } from "three/examples/jsm/loaders/FBXLoader.js";
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls.js";
import Stats from "stats.js";
const threeJsContainer = ref(null);
const progressBar = ref(null);
const selectedObject = ref(null);
onMounted(() => {
  // 创建场景
  const scene = new THREE.Scene();

  // 创建相机
  const camera = new THREE.PerspectiveCamera(
    75,
    window.innerWidth / window.innerHeight,
    0.1,
    100000
  );
  camera.position.set(0, 0, 3000); // 可能需要调整相机的位置
  camera.lookAt(scene.position); // 确保相机朝向场景中心
  // 创建渲染器
  const renderer = new THREE.WebGLRenderer();
  renderer.setSize(window.innerWidth, window.innerHeight);
  threeJsContainer.value.appendChild(renderer.domElement);
  renderer.setClearColor(0x87ceeb); // 设置背景颜色为浅天蓝色
  // 创建Stats对象
  const stats = new Stats();
  stats.showPanel(0); // 0: fps, 1: ms, 2: mb, 3+: custom
  threeJsContainer.value.appendChild(stats.domElement);
  // 创建灯光
  const light = new THREE.DirectionalLight(0xffffff, 1);
  light.position.set(1, 1, 1).normalize();
  scene.add(light);
  // 创建环境光
  const ambientLight = new THREE.AmbientLight(0xffffff); // 柔和的白光
  scene.add(ambientLight);
  // 调整方向光位置
  light.position.set(5, 10, 5);
  // 创建OrbitControls
  const controls = new OrbitControls(camera, renderer.domElement);
  controls.enableDamping = true; // 启用阻尼
  controls.dampingFactor = 0.05; // 阻尼系数
  controls.screenSpacePanning = false; // 如果设置为true，则可以水平移动相机
  controls.minDistance = 1; // 最小距离
  controls.maxDistance = 20000; // 最大距离
  //   controls.maxPolarAngle = Math.PI / 2; // 最大垂直角度
  // 加载FBX模型
  const loader = new FBXLoader();
  console.log("loader", loader);
  // 改进的加载模型函数，使用 async/await
  const loadModel = async (url) => {
    return new Promise((resolve, reject) => {
      loader.load(
        url,
        (object) => {
          resolve(object);
        },
        (progress) => {
          if (progress && progress.total) {
            const percentComplete = (progress.loaded / progress.total) * 100;
            progressBar.value.textContent = `Loading: ${Math.round(
              percentComplete
            )}%`;
          }
        },
        (error) => {
          reject(error);
        }
      );
    });
  };

  const init = async () => {
    try {
      const object = await loadModel(
        "/models/fbx/test.fbx"
      );
      scene.add(object);
      progressBar.value.style.display = "none";

      const box = new THREE.Box3().setFromObject(object);
      const center = box.getCenter(new THREE.Vector3());
      const size = box.getSize(new THREE.Vector3());

      object.position.set(0, -size.y / 2, 0);
      camera.position.set(0, size.y, 1.5 * size.z);
      controls.target.set(center.x, center.y, center.z);
      controls.update();
      // 获取FBX模型的元数据
      const metadata = object.metadata;
      console.log("metadata", metadata);
    } catch (error) {
      console.error("Error loading the model:", error);
    }
  };
  // loader.load(
  //   "/models/fbx/BYA-TA-TB-MBS-DD-CW-V1.0_（主楼南面幕墙）.fbx",
  //   (object) => {
  //     scene.add(object);
  //     // 可以打印模型边界框来检查模型大小和位置
  //     console.log(object);
  //     progressBar.value.style.display = "none"; // 加载完成后隐藏进度条
  //     // 计算模型的边界框
  //     const box = new THREE.Box3().setFromObject(object);
  //     const center = box.getCenter(object.position);
  //     const size = box.getSize(new THREE.Vector3());

  //     // 设置模型的位置
  //     object.position.set(0, -size.y / 2, 0); // 将模型底部置于原点

  //     // 设置相机的位置
  //     camera.position.set(0, size.y / 2, size.z); // 相机位于模型上方
  //     controls.target.set(center.x, center.y, center.z); // 设置控制器的目标为模型中心
  //     controls.update(); // 更新控制器
  //   },
  //   (progress) => {
  //     if (progress) {
  //       const percentComplete = (progress.loaded / progress.total) * 100;
  //       progressBar.value.textContent = `Loading: ${Math.round(
  //         percentComplete
  //       )}%`;
  //     }
  //   },
  //   (error) => {
  //     console.error(error);
  //   }
  // );

  // 创建射线投射器
  const raycaster = new THREE.Raycaster();
  const mouse = new THREE.Vector2();
  // 监听鼠标事件
  function onDocumentMouseDown(event) {
    event.preventDefault();
    mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
    mouse.y = -(event.clientY / window.innerHeight) * 2 + 1;
    raycaster.setFromCamera(mouse, camera);

    // 计算射线与物体的交点
    const intersects = raycaster.intersectObjects(scene.children, true);

    if (intersects.length > 0) {
      // 如果有交点，则选中第一个交点的物体
      const intersect = intersects[0];
      selectObject(intersect.object);
    }
  }
  // 选中对象并高亮显示
  function selectObject(object) {
    console.log("selectObject", object);
    // 取消之前选中的对象的高亮
    if (selectedObject.value) {
      if (selectedObject.value.material?.length) {
        selectedObject.value.material.forEach((element) => {
          element.emissive.set(0x000000);
        });
      } else {
        selectedObject.value.material.emissive.set(0x000000);
      }
    }
    // 设置新的选中对象
    selectedObject.value = object;
    // 高亮显示新选中的对象
    if (object.material) {
      if (object.material?.length) {
        object.material.forEach((element) => {
          element.emissive.set(0x000000);
        });
      } else {
        object.material.emissive.set(0xff0000);
      }
    }
    // 返回对象信息
    console.log("Selected object:", object.name);
  }
  // 渲染循环
  function animate() {
    requestAnimationFrame(animate);
    // 更新Stats
    stats.begin();
    // 更新controls
    controls.update();
    // 更新Stats
    stats.end();
    // 渲染场景
    renderer.render(scene, camera);
  }

  // 监听窗口大小改变
  window.addEventListener("resize", onWindowResize);
  // 监听鼠标点击事件
  threeJsContainer.value.addEventListener("click", onDocumentMouseDown);

  function onWindowResize() {
    camera.aspect = window.innerWidth / window.innerHeight;
    camera.updateProjectionMatrix();
    renderer.setSize(window.innerWidth, window.innerHeight);
  }

  // 开始渲染
  init();
  animate();
});
</script>

<style>
.three-js-container {
  width: 100%;
  height: 100vh;
}
.progress-bar {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 20px;
  background-color: #333;
  color: #fff;
  text-align: center;
  line-height: 20px;
}
</style>
